#! /usr/bin/env python
# -*- coding: utf-8 -*-

from django import forms
from web import models
from django.core.validators import RegexValidator, MinLengthValidator, EmailValidator
from django.core.exceptions import ValidationError
from django.conf import settings
import random
from utils.tencent.sms import send_single_sms
from django_redis import get_redis_connection
from utils.encrypt import md5
from web.form.bootstrap import BootStrap

import logging
logger = logging.getLogger('log')


class RegisterModelForm(BootStrap, forms.ModelForm):
    username = forms.CharField(label="用户名",
                               min_length=4,
                               max_length=32,
                               error_messages={
                                   'min_length': "用户名长度少于4个字符",
                                   'max_length': "用户名长度不能超过32字符"
                               },)
    pwd = forms.CharField(label="密码",
                          min_length=8,
                          max_length=32,
                          error_messages={
                              'min_length': "密码长度少于8个字符",
                              'max_length': "密码长度不能超过32字符"
                          },
                          widget=forms.PasswordInput())
    mobile_phone = forms.CharField(label="手机号",
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    code = forms.CharField(label="验证码", widget=forms.TextInput())
    confirm_pwd = forms.CharField(label="确认密码", widget=forms.PasswordInput())

    class Meta:
        model = models.UserInfo
        fields = ['username', 'email', 'pwd', 'confirm_pwd', 'mobile_phone', 'code']

    def clean_username(self):
        username = self.cleaned_data["username"]
        exist = models.UserInfo.objects.filter(username=username).exists()
        if exist:
            self.add_error("username", "用户名已存在")
        return username

    def clean_pwd(self):
        """ 加密密码"""
        pwd = self.cleaned_data["pwd"]

        return md5(pwd)

    def clean_email(self):
        email = self.cleaned_data['email']

        # 校验数据库中是否存在邮箱
        exist = models.UserInfo.objects.filter(email=email).exists()

        if exist:
            self.add_error("email", "邮箱已注册")
        return email

    def clean_confirm_pwd(self):
        pwd = self.cleaned_data.get('pwd')
        confirm_pwd = self.cleaned_data['confirm_pwd']
        if pwd != md5(confirm_pwd):
            self.add_error("confirm_pwd", "两次密码不一致")
        return confirm_pwd

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']

        # 校验数据库中是否存在手机号
        exist = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exist:
            self.add_error("mobile_phone", "手机号已注册")
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data["code"].strip()
        mobile_phone = self.cleaned_data["mobile_phone"]
        conn = get_redis_connection()
        code_in_redis = conn.get(mobile_phone)

        if code_in_redis is None:
            raise ValidationError("验证码失效或未发送")
        if bytes(str(code), encoding='utf-8') != code_in_redis:
            raise ValidationError("验证码错误")

        return code


class SmsForm(forms.Form):
    """ 表单验证手机号 """
    mobile_phone = forms.CharField(label="手机号", validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        """ 手机校验钩子"""
        mobile_phone = self.cleaned_data['mobile_phone']

        tpl = self.request.POST.get("tpl")
        template_sms_id = settings.TEMPLATE_SMS.get(tpl)
        if not template_sms_id:
            raise ValidationError("短信模板错误")

        # 校验数据库中是否存在手机号
        exist = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()

        # 通过tpl区分注册or登录
        if tpl == 'register':
            if exist:
                raise ValidationError("手机号已存在")
        if tpl == 'login':
            if not exist:
                raise ValidationError("手机号不存在")

        # 发短信 写Redis
        code = random.randrange(1000, 9999)
        # code = 6666
        sms = send_single_sms(mobile_phone, [code, 10], template_sms_id)
        logger.info(f"phone number: {mobile_phone}, code: {code}, result: {sms}")
        if sms['result'] != 0:
            raise ValidationError(f"短信发送失败, {sms['errmsg']}")

        # 验证码写入Redis
        conn = get_redis_connection()
        conn.set(mobile_phone, code, ex=10*60)

        return mobile_phone


class LoginSmsForm(BootStrap, forms.Form):
    mobile_phone = forms.CharField(label="手机号",
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    code = forms.CharField(label="验证码", widget=forms.TextInput())

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']

        # 根据手机号获取用户对象并返回
        user_obj = models.UserInfo.objects.filter(mobile_phone=mobile_phone).first()
        if not user_obj:
            self.add_error("mobile_phone", "手机号未注册")
        return user_obj

    def clean_code(self):
        code = self.cleaned_data["code"].strip()
        # 从用户对象中获取手机号
        mobile_phone = self.cleaned_data.get("mobile_phone").mobile_phone
        conn = get_redis_connection()
        code_in_redis = conn.get(mobile_phone)

        if code_in_redis is None:
            raise ValidationError("验证码失效或未发送")
        if bytes(str(code), encoding='utf-8') != code_in_redis:
            raise ValidationError("验证码错误")
        return code


class LoginForm(BootStrap, forms.Form):
    username = forms.CharField(label="邮箱或手机号",
                               min_length=4,
                               max_length=32,
                               error_messages={
                                   'min_length': "用户名长度少于4个字符",
                                   'max_length': "用户名长度不能超过32字符"
                               },)
    pwd = forms.CharField(label="密码",
                          min_length=8,
                          max_length=32,
                          error_messages={
                              'min_length': "密码长度少于8个字符",
                              'max_length': "密码长度不能超过32字符"
                          },
                          widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label="图片验证码")

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_code(self):
        code = self.cleaned_data.get("code")
        session_code = self.request.session.get("img_code")

        if not session_code:
            raise ValidationError("验证码已过期，请重新输入")

        if code.strip().upper() != session_code.upper():
            raise ValidationError("验证码错误")

        return code

    def clean_pwd(self):
        """ 加密密码"""
        pwd = self.cleaned_data["pwd"]

        return md5(pwd)


